package com.medusa.aps.business.modules.plan.mp.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.aps.business.model.pagination.Page;
import com.medusa.aps.business.modules.demand.model.input.ScheduleProcessDetailsParam;
import com.medusa.aps.business.modules.demand.model.output.ScheduleProcessDetailsVO;
import com.medusa.aps.business.modules.plan.model.input.ProcessDetailsParam;
import com.medusa.aps.business.modules.plan.model.output.ProcessDetailsVO;
import com.medusa.aps.business.modules.plan.mp.entity.ProcessDetails;
import com.medusa.aps.business.modules.plan.mp.mapper.ProcessDetailsMapper;
import com.medusa.aps.business.modules.plan.mp.service.ProcessDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 工序明细服务实现类
 *
 * @author yuxh
 * @since 2023-08-14 17:37:48
 */
@Slf4j
@Service("processDetailsService")
public class ProcessDetailsServiceImpl extends ServiceImpl<ProcessDetailsMapper, ProcessDetails> implements ProcessDetailsService {

    @Override
    public Page<ProcessDetailsVO> selectPage(Page<ProcessDetails> page, ProcessDetailsParam processDetails) {
        return selectPageBase(page, processDetails).convert(ProcessDetails::toProcessDetailsVO);
    }

    public Page<ProcessDetails> selectPageBase(Page<ProcessDetails> page, ProcessDetailsParam processDetails) {
        return baseMapper.selectProcessDetailPage(processDetails, page);
    }

    @Override
    public boolean isExistProcessPlan(Set<Long> equipmentIds, LocalDateTime time) {
        // 判断是否已生成相对 基准时间的 的未来的了工序计划
        if (CollUtil.isEmpty(equipmentIds)) {
            return false;
        }
        //   计划结束时间大于 基准时间 time
        return getExistProcessPlanEquipmentIds(equipmentIds, time).size() > 0;
    }

    @Override
    public Set<Long> getExistProcessPlanEquipmentIds(Set<Long> equipmentIds, LocalDateTime time) {
        // 根据设备 id 集合、基准时间的 获取已生成的未来的了工序计划的设备 id 集合
        if (CollUtil.isEmpty(equipmentIds)) {
            return Set.of();
        }
        // 实际结束时间 不为空 判断实际结束时间 否则 判断计划结束时间 是否大于当前时间
        return this.lambdaQuery()
                .select(ProcessDetails::getEquipmentId)
                .in(ProcessDetails::getEquipmentId, equipmentIds)
                .apply("IFNULL(actual_end_time,planned_end_time) >= {0}", time)
                .groupBy(ProcessDetails::getEquipmentId)
                .list()
                .stream()
                .map(ProcessDetails::getEquipmentId)
                .collect(Collectors.toSet());
    }

    /**
     * 根据设备id 日期 判断已排产设备在当天是否工作
     *
     * @param equipmentId 加工设备id
     * @param date        日期
     * @return 是否在指定日期已排产
     */
    @Override
    public Boolean isExistProcessPlanEquipment(Long equipmentId, LocalDate date) {
        return this.lambdaQuery()
                .select(ProcessDetails::getEquipmentId)
                .eq(ProcessDetails::getEquipmentId, equipmentId)
                .apply("IFNULL(actual_end_time,planned_end_time) >= {0}", date.atStartOfDay())
                .exists();

    }

    @Override
    public Page<ScheduleProcessDetailsVO> scheduleProcessDetail(ScheduleProcessDetailsParam scheduleProcessDetailsParam) {
        return baseMapper.scheduleProcessDetail(scheduleProcessDetailsParam, new Page<>(scheduleProcessDetailsParam.getCurrent(), scheduleProcessDetailsParam.getSize()));
    }
}

